import {isEmpty} from '../utils'
import os from 'os'
import logging from '../logging'
import fs from 'fs'
import process from 'process'
import path from 'path'
import fse from 'fs-extra'

/**
 * 缓存一个目录到指定的工具和版本下
 * @param sourceDir 源目录
 * @param toolName 工具名字
 * @param toolVersion 工具版本
 * @param osArch 系统架构, Optional
 * @returns {Promise<string|*|string>} 缓存的目标目录
 */
export async function cacheDir(
    sourceDir: string,
    toolName: string,
    toolVersion: string,
    osArch?: string
): Promise<string> {
    if (isEmpty(sourceDir)) {
        throw new Error('sourceDir is empty')
    }

    if (isEmpty(osArch)) {
        osArch = os.arch()
    }

    logging.debug(
        `Caching dir from ${sourceDir}, toolName=${toolName}, toolVersion=${toolVersion}, osArch=${osArch}`
    )
    const toolCacheDir: string = getToolVersionCacheDir(
        toolName,
        toolVersion,
        osArch
    )
    if (fse.existsSync(toolCacheDir)) {
        fs.rmSync(toolCacheDir, {recursive: true, force: true})
    }
    fs.mkdirSync(toolCacheDir, {recursive: true})

    fse.copySync(sourceDir, toolCacheDir)
    recordCompletedFile(toolName, toolVersion, osArch)
    return toolCacheDir
}

/**
 * 缓存文件到指定工具和版本下.
 * @param sourceFile 源文件
 * @param targetFile 目标文件
 * @param toolName 工具名字
 * @param toolVersion 工具版本
 * @param osArch 系统架构，Optional
 * @returns {Promise<string|*|string>} 缓存的目标目录
 */
export async function cacheFile(
    sourceFile: string,
    targetFile: string,
    toolName: string,
    toolVersion: string,
    osArch?: string
): Promise<string> {
    if (isEmpty(sourceFile)) {
        throw new Error('sourceFile is empty')
    }

    if (isEmpty(osArch)) {
        osArch = os.arch()
    }

    logging.debug(
        `Caching file from ${sourceFile}, toolName=${toolName}, toolVersion=${toolVersion}, osArch=${osArch}`
    )
    const toolCacheDir: string = getToolVersionCacheDir(
        toolName,
        toolVersion,
        osArch
    )
    const destToolCacheFile: string = path.join(toolCacheDir, targetFile)
    fse.copySync(sourceFile, destToolCacheFile, {overwrite: true})

    recordCompletedFile(toolName, toolVersion, osArch)
    return toolCacheDir
}

function recordCompletedFile(
    toolName: string,
    toolVersion: string,
    osArch?: string
): void {
    const completedFile: string = getToolVersionCacheCompleteFilePath(
        toolName,
        toolVersion,
        osArch
    )
    fs.writeFileSync(completedFile, new Date(Date.now()).toLocaleTimeString())
}

export function getToolCacheBaseDir(): string {
    const toolCacheDir = process.env['FLOW_RUNNER_TOOL_CACHE_DIR'] as string
    if (isEmpty(toolCacheDir)) {
        throw new Error("missing 'FLOW_RUNNER_TOOL_CACHE_DIR' env variables")
    }
    return toolCacheDir
}

export function getToolCacheDir(toolName: string): string {
    const toolCacheBaseDir: string = getToolCacheBaseDir()
    return path.join(toolCacheBaseDir, toolName)
}

export function getToolVersionCacheDir(
    toolName: string,
    toolVersion: string,
    osArch?: string
): string {
    const toolCacheBaseDir = getToolCacheBaseDir()
    if (isEmpty(osArch) || osArch == null) {
        osArch = os.arch()
    }
    return path.join(toolCacheBaseDir, toolName, toolVersion, osArch)
}

export function getToolVersionCacheCompleteFilePath(
    toolName: string,
    toolVersion: string,
    osArch?: string
): string {
    const toolCacheDir = getToolVersionCacheDir(toolName, toolVersion, osArch)
    return path.join(toolCacheDir, 'cache.completed')
}
